package com.fw.service.merchantuser.impl;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.log4j.Logger;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;

import com.fw.service.applicationlog.ApplicationLogService;
import com.fw.service.applicationlog.bean.ApplicationLogBean;
import com.fw.service.auditlog.AuditLogService;
import com.fw.service.auditlog.bean.AuditLogBean;
import com.fw.service.bean.EntryBean;
import com.fw.service.bean.ErrorBean;
import com.fw.service.bean.SearchCriteriaBean;
import com.fw.service.bean.SearchResultBean;
import com.fw.service.formvalidator.FormValidatorService;
import com.fw.service.merchantuser.MerchantUserService;
import com.fw.service.merchantuser.bean.MerchantUserBean;
import com.fw.service.merchantuser.bean.SearchMerchantUserBean;
import com.fw.service.passwordpolicy.PasswordPolicyService;
import com.fw.service.passwordpolicy.bean.PasswordPolicyBean;
import com.fw.service.persistence.MerchantUserPersistenceService;
import com.fw.service.persistence.dto.Error;
import com.fw.service.persistence.dto.MerchantUser;
import com.fw.service.property.PropertyService;
import com.fw.util.DateUtils;
import com.fw.util.PageRequestUtils;
import com.fw.util.PasswordUtils;
import com.fw.util.StringUtils;

public class MerchantUserServiceImpl implements MerchantUserService {

    private static Logger log = Logger.getLogger(MerchantUserServiceImpl.class.getName());

    @Autowired
    private PropertyService propertyService;

    @Autowired
    private ApplicationLogService applicationLogService;

    @Autowired
    private AuditLogService auditLogService;

    @Autowired
    private FormValidatorService formValidatorService;

    @Autowired
    private MerchantUserPersistenceService merchantUserPersistenceService;

    @Autowired
    private PasswordPolicyService passwordPolicyService;

    @Override
    public List<EntryBean<String, Serializable>> createMerchantUser(MerchantUserBean merchantUserBean) {
	String clazz = MerchantUserService.class.getName();
	String method = "createMerchantUser";
	List<EntryBean<String, Serializable>> entryBeans = null;
	try {
	    ApplicationLogBean applicationLogBean = new ApplicationLogBean();
	    applicationLogBean.setType(ApplicationLogBean.TYPE_INFO);
	    applicationLogBean.setClazz(clazz);
	    applicationLogBean.setMethod(method);
	    applicationLogBean.setMessage(method);
	    applicationLogService.createApplicationLog(applicationLogBean);

	    if (merchantUserBean != null) {
		entryBeans = new ArrayList<EntryBean<String, Serializable>>();
		// validate
		List<Error> errors = formValidatorService.validate(clazz, method, merchantUserBean);
		List<ErrorBean> errorBeans = new ArrayList<ErrorBean>();
		if (errors != null && !errors.isEmpty()) {
		    for (Error error : errors) {
			ErrorBean errorBean = new ErrorBean();
			BeanUtils.copyProperties(error, errorBean);
			errorBeans.add(errorBean);
		    }
		}
		// validate unique
		if (!this.checkUniqueUsername(merchantUserBean.getUsername())) {
		    ErrorBean errorBean = new ErrorBean();
		    errorBean.setErrorCode("errors.com.fw.service.merchantuser.MerchantUserService.createMerchantUser.usernameExist");
		    errorBeans.add(errorBean);
		}
		if (errorBeans != null && !errorBeans.isEmpty()) {
		    entryBeans.add(new EntryBean<String, Serializable>(List.class.getName() + "." + ErrorBean.class.getName(),
			    (Serializable) errorBeans));
		} else {
		    Date currentDate = DateUtils.getCurrentDate();
		    String currentDateStr = StringUtils.formatDate(currentDate, StringUtils.PATTERN_DATETIME_PERSISTENCE);
		    // save
		    MerchantUser merchantUser = new MerchantUser();
		    BeanUtils.copyProperties(merchantUserBean, merchantUser);
		    merchantUser.setStatus(MerchantUser.STATUS_ACTIVE);
		    merchantUser.setUserType(MerchantUser.USER_TYPE_AEON_USER);
		    Calendar calendar = Calendar.getInstance(Locale.ENGLISH);
		    // load password policy
		    PasswordPolicyBean passwordPolicyBean = passwordPolicyService.getPasswordPolicy();
		    Integer passwordExpiryPeriodDay = 15;
		    if (passwordPolicyBean != null && passwordPolicyBean.getPasswordExpiryPeriodDay() != null) {
			passwordExpiryPeriodDay = passwordPolicyBean.getPasswordExpiryPeriodDay();
		    }
		    calendar.add(Calendar.DAY_OF_YEAR, passwordExpiryPeriodDay);
		    calendar.set(Calendar.HOUR_OF_DAY, 0);
		    calendar.set(Calendar.MINUTE, 0);
		    calendar.set(Calendar.SECOND, 0);
		    calendar.set(Calendar.MILLISECOND, 0);
		    merchantUser.setExpiredDate(StringUtils.formatDate(calendar.getTime(), StringUtils.PATTERN_DATE_PERSISTENCE));
		    merchantUser.setCreateBy(merchantUserBean.getLoginUsername());
		    merchantUser.setCreateDatetime(currentDateStr);
		    merchantUser.setLastUpdateBy(merchantUserBean.getLoginUsername());
		    merchantUser.setLastUpdateDatetime(currentDateStr);
		    // auto create password
		    String password = passwordPolicyService.generatePassword(Boolean.TRUE);
		    String passwordHash = PasswordUtils.generateSecuredPasswordHash(password);
		    this.createMerchantUserPasswordHistory(merchantUser.getId(), passwordHash, currentDateStr);

		    merchantUser.setPasswordHash(passwordHash);
		    merchantUser.setPasswordStatus(MerchantUser.PASSWORD_STATUS_FORCE_CHANGE);
		    merchantUser = merchantUserPersistenceService.save(merchantUser);

		    MerchantUserBean resultBoUserBean = new MerchantUserBean();
		    BeanUtils.copyProperties(merchantUser, resultBoUserBean);
		    resultBoUserBean.setId(merchantUser.getId());
		    resultBoUserBean.setPassword(password);
		    // audit log
		    String logActionType = propertyService.getProperty("auditlog." + clazz + "." + method);
		    if (logActionType != null) {
			AuditLogBean auditLogBean = new AuditLogBean();
			auditLogBean.setLogActionType(logActionType);
			auditLogBean.setDescription(merchantUserBean.getUsername() + " created by " + merchantUserBean.getLoginUsername());
			auditLogBean.setGroupId(merchantUserBean.getLoginRoleId());
			auditLogBean.setUserId(merchantUserBean.getLoginUserId());
			auditLogBean.setDateTime(currentDateStr);
			auditLogBean.setUserIp(merchantUserBean.getUserIp());
			auditLogService.createAuditLog(auditLogBean);
		    }
		    entryBeans.add(new EntryBean<String, Serializable>(resultBoUserBean.getClass().getName(), resultBoUserBean));
		}
	    }
	} catch (Exception e) {
	    ApplicationLogBean applicationLogBean = new ApplicationLogBean();
	    applicationLogBean.setType(ApplicationLogBean.TYPE_ERROR);
	    applicationLogBean.setClazz(clazz);
	    applicationLogBean.setMethod(method);
	    applicationLogBean.setMessage(e.getMessage());
	    applicationLogService.createApplicationLog(applicationLogBean);
	}
	return entryBeans;
    }

    @Override
    public MerchantUserBean getMerchantUser(Long id) {
	MerchantUserBean merchantUserBean = null;
	try {
	    MerchantUser merchantUser = merchantUserPersistenceService.findOne(id);
	    if (merchantUser != null && !MerchantUser.STATUS_CLOSED.equals(merchantUser.getStatus())) {
		merchantUserBean = new MerchantUserBean();
		BeanUtils.copyProperties(merchantUser, merchantUserBean);
		merchantUserBean.setId(merchantUser.getId());
	    }
	} catch (Exception e) {
	    log.error(e.getMessage(), e);
	}
	return merchantUserBean;
    }

    @Override
    public List<EntryBean<String, Serializable>> updateMerchantUser(MerchantUserBean merchantUserBean) {
	String clazz = MerchantUserService.class.getName();
	String method = "updateMerchantUser";
	List<EntryBean<String, Serializable>> entryBeans = null;
	MerchantUser merchantUser = null;
	try {

	    if (merchantUserBean != null) {
		merchantUser = merchantUserPersistenceService.findOne(merchantUserBean.getId());
		if (merchantUser != null && isDataChange(merchantUser, merchantUserBean)) {

		    ApplicationLogBean applicationLogBean = new ApplicationLogBean();
		    applicationLogBean.setType(ApplicationLogBean.TYPE_INFO);
		    applicationLogBean.setClazz(clazz);
		    applicationLogBean.setMethod(method);
		    applicationLogBean.setMessage(method);
		    applicationLogService.createApplicationLog(applicationLogBean);

		    entryBeans = new ArrayList<EntryBean<String, Serializable>>();
		    // validate
		    List<Error> errors = formValidatorService.validate(clazz, method, merchantUserBean);
		    List<ErrorBean> errorBeans = new ArrayList<ErrorBean>();
		    if (errors != null && !errors.isEmpty()) {
			for (Error error : errors) {
			    ErrorBean errorBean = new ErrorBean();
			    BeanUtils.copyProperties(error, errorBean);
			    errorBeans.add(errorBean);
			}
		    }
		    if (errorBeans != null && !errorBeans.isEmpty()) {
			entryBeans.add(new EntryBean<String, Serializable>(List.class.getName() + "." + ErrorBean.class.getName(),
				(Serializable) errorBeans));
		    } else {
			// if (merchantUser != null && !MerchantUser.STATUS_INACTIVE.equals(merchantUser.getStatus())) {
			Date currentDate = DateUtils.getCurrentDate();
			String currentDateStr = StringUtils.formatDate(currentDate, StringUtils.PATTERN_DATETIME_PERSISTENCE);
			// copy from bean
			merchantUser.setEmail(merchantUserBean.getEmail());
			merchantUser.setName(merchantUserBean.getName());
			merchantUser.setRole(merchantUserBean.getRole());

			String password = null;
			if ((MerchantUser.STATUS_CLOSED.equals(merchantUser.getStatus())
				|| MerchantUser.STATUS_EXPIRED.equals(merchantUser.getStatus())
				|| MerchantUser.STATUS_LOCKED.equals(merchantUser.getStatus()) || MerchantUser.STATUS_INACTIVE
				    .equals(merchantUser.getStatus())) && MerchantUser.STATUS_ACTIVE.equals(merchantUserBean.getStatus())) {
			    // auto create new password
			    password = passwordPolicyService.generatePassword(Boolean.TRUE);
			    String passwordHash = PasswordUtils.generateSecuredPasswordHash(password);
			    this.createMerchantUserPasswordHistory(merchantUser.getId(), passwordHash, currentDateStr);

			    merchantUser.setPasswordHash(passwordHash);
			    merchantUser.setPasswordStatus(MerchantUser.PASSWORD_STATUS_FORCE_CHANGE);

			    // reset login attempt count
			    // MerchantUserLogin merchantUserLogin = merchantUserLoginDAO.findByUserId(merchantUser.getId());
			    // if (merchantUserLogin != null) {
			    // merchantUserLogin.setLoginAttemptCount(0);
			    // merchantUserLoginDAO.save(merchantUserLogin);
			    // }
			}
			merchantUser.setStatus(merchantUserBean.getStatus());

			merchantUser.setLastUpdateBy(merchantUserBean.getLoginUsername());
			merchantUser.setLastUpdateDatetime(currentDateStr);
			merchantUser = merchantUserPersistenceService.save(merchantUser);
			MerchantUserBean resultBoUserBean = new MerchantUserBean();
			BeanUtils.copyProperties(merchantUser, resultBoUserBean);
			resultBoUserBean.setId(merchantUser.getId());
			resultBoUserBean.setPassword(password);

			// audit log
			String logActionType = propertyService.getProperty("auditlog." + clazz + "." + method);
			if (logActionType != null) {
			    AuditLogBean auditLogBean = new AuditLogBean();
			    auditLogBean.setLogActionType(logActionType);
			    auditLogBean.setDescription(merchantUserBean.getLoginUsername() + " edited " + merchantUserBean.getUsername()
				    + " profile");
			    auditLogBean.setGroupId(merchantUserBean.getLoginRoleId());
			    auditLogBean.setUserId(merchantUserBean.getLoginUserId());
			    auditLogBean.setDateTime(currentDateStr);
			    auditLogBean.setUserIp(merchantUserBean.getUserIp());
			    auditLogService.createAuditLog(auditLogBean);
			}
			entryBeans.add(new EntryBean<String, Serializable>(resultBoUserBean.getClass().getName(), resultBoUserBean));
			// }
		    }
		} else {
		    entryBeans = new ArrayList<EntryBean<String, Serializable>>();
		    entryBeans.add(new EntryBean<String, Serializable>(merchantUserBean.getClass().getName(), merchantUserBean));
		}
	    }
	} catch (Exception e) {
	    ApplicationLogBean applicationLogBean = new ApplicationLogBean();
	    applicationLogBean.setType(ApplicationLogBean.TYPE_ERROR);
	    applicationLogBean.setClazz(clazz);
	    applicationLogBean.setMethod(method);
	    applicationLogBean.setMessage(e.getMessage());
	    applicationLogService.createApplicationLog(applicationLogBean);
	}
	return entryBeans;
    }

    @Override
    public List<EntryBean<String, Serializable>> deleteMerchantUser(MerchantUserBean merchantUserBean) {
	String clazz = MerchantUserService.class.getName();
	String method = "deleteMerchantUser";
	List<EntryBean<String, Serializable>> entryBeans = null;
	MerchantUser merchantUser = null;
	try {
	    if (merchantUserBean != null) {
		Date currentDate = DateUtils.getCurrentDate();
		String currentDateStr = StringUtils.formatDate(currentDate, StringUtils.PATTERN_DATETIME_PERSISTENCE);
		entryBeans = new ArrayList<EntryBean<String, Serializable>>();

		// validate
		List<Error> errors = formValidatorService.validate(clazz, method, merchantUserBean);
		List<ErrorBean> errorBeans = new ArrayList<ErrorBean>();
		if (errors != null && !errors.isEmpty()) {
		    for (Error error : errors) {
			ErrorBean errorBean = new ErrorBean();
			BeanUtils.copyProperties(error, errorBean);
			errorBeans.add(errorBean);
		    }
		} else {
		    Long merchantUserId = merchantUserBean.getId();
		    merchantUser = merchantUserPersistenceService.findOne(merchantUserId);
		    if (merchantUser == null) {
			errorBeans.add(new ErrorBean(
				"errors.com.fw.service.merchantuser.MerchantUserService.deleteMerchantUser.notfoundMerchantUser"));
		    }
		}
		// result
		if (errorBeans != null && !errorBeans.isEmpty()) {
		    entryBeans.add(new EntryBean<String, Serializable>(List.class.getName() + "." + ErrorBean.class.getName(),
			    (Serializable) errorBeans));
		} else {

		    // update status
		    merchantUser.setStatus(MerchantUser.STATUS_INACTIVE);
		    merchantUser.setLastUpdateBy(merchantUserBean.getLoginUsername());
		    merchantUser.setLastUpdateDatetime(currentDateStr);
		    merchantUser = merchantUserPersistenceService.save(merchantUser);

		    MerchantUserBean resultBoUserBean = new MerchantUserBean();
		    BeanUtils.copyProperties(merchantUser, resultBoUserBean);
		    resultBoUserBean.setId(merchantUser.getId());

		    // audit log
		    String logActionType = propertyService.getProperty("auditlog." + clazz + "." + method);
		    if (logActionType != null) {
			AuditLogBean auditLogBean = new AuditLogBean();
			auditLogBean.setLogActionType(logActionType);
			auditLogBean.setDescription("Merchant User, Username: " + merchantUser.getUsername() + " deleted by "
				+ merchantUserBean.getLoginUsername());
			auditLogBean.setGroupId(merchantUserBean.getLoginRoleId());
			auditLogBean.setUserId(merchantUserBean.getLoginUserId());
			auditLogBean.setDateTime(currentDateStr);
			auditLogBean.setUserIp(merchantUserBean.getUserIp());
			auditLogService.createAuditLog(auditLogBean);
		    }
		    entryBeans.add(new EntryBean<String, Serializable>(resultBoUserBean.getClass().getName(), resultBoUserBean));
		}
	    }
	} catch (Exception e) {
	    ApplicationLogBean applicationLogBean = new ApplicationLogBean();
	    applicationLogBean.setType(ApplicationLogBean.TYPE_ERROR);
	    applicationLogBean.setClazz(clazz);
	    applicationLogBean.setMethod(method);
	    applicationLogBean.setMessage(e.getMessage());
	    applicationLogService.createApplicationLog(applicationLogBean);
	}
	return entryBeans;
    }

    @Override
    public Boolean checkUniqueUsername(String username) {
	Boolean result = Boolean.FALSE;
	try {
	    List<MerchantUser> merchantUsers = merchantUserPersistenceService.selectByUsernameAndStatus(username, null);
	    if (merchantUsers == null || merchantUsers.isEmpty()) {
		result = Boolean.TRUE;
	    }
	} catch (Exception e) {
	    log.error(e.getMessage(), e);
	}
	return result;
    }

    @Override
    public List<MerchantUserBean> selectAllMerchantUser() {
	List<MerchantUserBean> merchantUserBeans = null;
	try {
	    List<MerchantUser> merchantUsers = merchantUserPersistenceService.selectByStatus(MerchantUser.STATUS_ACTIVE);
	    if (merchantUsers != null && !merchantUsers.isEmpty()) {
		merchantUserBeans = new ArrayList<MerchantUserBean>();
		for (MerchantUser merchantUser : merchantUsers) {
		    MerchantUserBean merchantUserBean = new MerchantUserBean();
		    BeanUtils.copyProperties(merchantUser, merchantUserBean);
		    merchantUserBean.setId(merchantUser.getId());
		    merchantUserBeans.add(merchantUserBean);
		}
	    }
	} catch (Exception e) {
	    log.error(e.getMessage(), e);
	}
	return merchantUserBeans;
    }

    @Override
    public SearchResultBean<MerchantUserBean> selectMerchantUser(SearchCriteriaBean<SearchMerchantUserBean> searchCriteriaBean) {
	SearchResultBean<MerchantUserBean> searchResultBean = null;
	try {
	    if (searchCriteriaBean != null) {
		SearchMerchantUserBean searchMerchantUserBean = searchCriteriaBean.getCriteriaBean();
		if (searchMerchantUserBean != null) {
		    final String username = searchMerchantUserBean.getUsername();
		    final String name = searchMerchantUserBean.getName();
		    final String email = searchMerchantUserBean.getEmail();
		    final String merchantID = searchMerchantUserBean.getMerchantID();
		    final String parentID = searchMerchantUserBean.getParentID();
		    final String role = searchMerchantUserBean.getRole();
		    final String status = searchMerchantUserBean.getStatus();
		    final String createBy = searchMerchantUserBean.getCreateBy();
		    final String lastUpdateBy = searchMerchantUserBean.getLastUpdateBy();
		    final Date expiredDateFrom = searchMerchantUserBean.getExpiredDateFrom();
		    final Date expiredDateTo = searchMerchantUserBean.getExpiredDateTo();
		    final Date createDateFrom = searchMerchantUserBean.getCreateDateFrom();
		    final Date createDateTo = searchMerchantUserBean.getCreateDateTo();
		    final Date lastUpdateDateFrom = searchMerchantUserBean.getLastUpdateDateFrom();
		    final Date lastUpdateDateTo = searchMerchantUserBean.getLastUpdateDateTo();

		    Specification<MerchantUser> specification = new Specification<MerchantUser>() {
			@Override
			public Predicate toPredicate(Root<MerchantUser> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
			    List<Predicate> predicates = new ArrayList<Predicate>();
			    if (username != null && !username.isEmpty()) {
				predicates.add(cb.like(root.<String> get("username"), "%" + username + "%"));
			    }
			    if (email != null && !email.isEmpty()) {
				predicates.add(cb.like(root.<String> get("email"), "%" + email + "%"));
			    }
			    if (merchantID != null && !merchantID.isEmpty()) {
				predicates.add(cb.like(root.<String> get("merchantID"), "%" + merchantID + "%"));
			    }
			    if (parentID != null && !parentID.isEmpty()) {
				predicates.add(cb.like(root.<String> get("parentID"), "%" + parentID + "%"));
			    }
			    if (name != null && !name.isEmpty()) {
				predicates.add(cb.like(root.<String> get("name"), "%" + name + "%"));
			    }
			    if (role != null && !role.isEmpty()) {
				predicates.add(cb.equal(root.<String> get("role"), role));
			    }
			    if (status != null && !status.isEmpty()) {
				predicates.add(cb.equal(root.<String> get("status"), status));
			    } else {
				predicates.add(cb.notEqual(root.<String> get("status"), MerchantUser.STATUS_CLOSED));
			    }
			    if (createBy != null && !createBy.isEmpty()) {
				predicates.add(cb.like(root.<String> get("createBy"), "%" + createBy + "%"));
			    }
			    if (lastUpdateBy != null && !lastUpdateBy.isEmpty()) {
				predicates.add(cb.like(root.<String> get("lastUpdateBy"), "%" + lastUpdateBy + "%"));
			    }
			    if (expiredDateFrom != null) {
				predicates.add(cb.greaterThanOrEqualTo(root.<String> get("expiredDate"),
					StringUtils.formatDate(expiredDateFrom, StringUtils.PATTERN_DATE_PERSISTENCE)));
			    }
			    if (expiredDateTo != null) {
				predicates.add(cb.lessThanOrEqualTo(root.<String> get("expiredDate"),
					StringUtils.formatDate(expiredDateTo, StringUtils.PATTERN_DATE_PERSISTENCE)));
			    }
			    if (createDateFrom != null) {
				predicates.add(cb.greaterThanOrEqualTo(root.<String> get("createDatetime"), StringUtils.formatDate(
					DateUtils.getFromDate(createDateFrom), StringUtils.PATTERN_DATETIME_PERSISTENCE)));
			    }
			    if (createDateTo != null) {
				predicates
					.add(cb.lessThanOrEqualTo(root.<String> get("createDatetime"), StringUtils.formatDate(
						DateUtils.getToDate(createDateTo), StringUtils.PATTERN_DATETIME_PERSISTENCE)));
			    }
			    if (lastUpdateDateFrom != null) {
				predicates.add(cb.greaterThanOrEqualTo(root.<String> get("lastUpdateDatetime"), StringUtils.formatDate(
					DateUtils.getFromDate(lastUpdateDateFrom), StringUtils.PATTERN_DATETIME_PERSISTENCE)));
			    }
			    if (lastUpdateDateTo != null) {
				predicates.add(cb.lessThanOrEqualTo(root.<String> get("lastUpdateDatetime"), StringUtils.formatDate(
					DateUtils.getToDate(lastUpdateDateTo), StringUtils.PATTERN_DATETIME_PERSISTENCE)));
			    }
			    Predicate result = cb.conjunction();
			    for (Predicate predicate : predicates) {
				result.getExpressions().add(predicate);
			    }
			    return result;
			}
		    };
		    System.out.println("specification.toString()"+specification.toString());
		    System.out.println("PageRequestUtils.getPageRequest(searchCriteriaBean)"+PageRequestUtils.getPageRequest(searchCriteriaBean));
		    Page<MerchantUser> page = merchantUserPersistenceService.findAll(specification,
			    PageRequestUtils.getPageRequest(searchCriteriaBean));
		    if (page != null) {
			searchResultBean = new SearchResultBean<MerchantUserBean>();
			searchResultBean.setTotalElements(page.getTotalElements());
			searchResultBean.setTotalPages(page.getTotalPages());
			List<MerchantUserBean> content = new ArrayList<MerchantUserBean>();
			List<MerchantUser> merchantUsers = page.getContent();
			if (merchantUsers != null && !merchantUsers.isEmpty()) {
			    for (MerchantUser merchantUser : merchantUsers) {
				MerchantUserBean bean = new MerchantUserBean();
				BeanUtils.copyProperties(merchantUser, bean);
				bean.setId(merchantUser.getId());
				content.add(bean);
			    }
			}
			searchResultBean.setContent(content);
		    }
		}
	    }
	} catch (Exception e) {
	    log.error(e.getMessage(), e);
	}
	return searchResultBean;
    }

    @Override
    public List<EntryBean<String, Serializable>> resetPasswordMerchantUser(MerchantUserBean merchantUserBean) {
	String clazz = MerchantUserService.class.getName();
	String method = "resetPasswordMerchantUser";
	List<EntryBean<String, Serializable>> entryBeans = null;
	try {
	    if (merchantUserBean != null && merchantUserBean.getId() != null) {
		entryBeans = new ArrayList<EntryBean<String, Serializable>>();
		List<ErrorBean> errorBeans = new ArrayList<ErrorBean>();
		MerchantUser merchantUser = merchantUserPersistenceService.findOne(merchantUserBean.getId());
		Date currentDate = DateUtils.getCurrentDate();
		String currentDateStr = StringUtils.formatDate(currentDate, StringUtils.PATTERN_DATETIME_PERSISTENCE);
		String password = passwordPolicyService.generatePassword(Boolean.TRUE);
		String passwordHash = PasswordUtils.generateSecuredPasswordHash(password);
		this.createMerchantUserPasswordHistory(merchantUser.getId(), passwordHash, currentDateStr);

		merchantUser.setPasswordHash(passwordHash);
		merchantUser.setPasswordStatus(MerchantUser.PASSWORD_STATUS_FORCE_CHANGE);
		merchantUser.setLastUpdateBy(merchantUserBean.getLoginUsername());
		merchantUser.setLastUpdateDatetime(currentDateStr);
		merchantUser = merchantUserPersistenceService.save(merchantUser);

		MerchantUserBean resultBoUserBean = new MerchantUserBean();
		BeanUtils.copyProperties(merchantUser, resultBoUserBean);
		resultBoUserBean.setId(merchantUser.getId());
		resultBoUserBean.setPassword(password);
		// audit log
		String logActionType = propertyService.getProperty("auditlog." + clazz + "." + method);
		if (logActionType != null) {
		    AuditLogBean auditLogBean = new AuditLogBean();
		    auditLogBean.setLogActionType(logActionType);
		    auditLogBean.setDescription(merchantUserBean.getLoginUsername() + " reset password " + merchantUserBean.getUsername());
		    auditLogBean.setGroupId(merchantUserBean.getLoginRoleId());
		    auditLogBean.setUserId(merchantUserBean.getLoginUserId());
		    auditLogBean.setDateTime(currentDateStr);
		    auditLogBean.setUserIp(merchantUserBean.getUserIp());
		    auditLogService.createAuditLog(auditLogBean);
		}
		if (errorBeans != null && !errorBeans.isEmpty()) {
		    entryBeans.add(new EntryBean<String, Serializable>(List.class.getName() + "." + ErrorBean.class.getName(),
			    (Serializable) errorBeans));
		} else {
		    entryBeans.add(new EntryBean<String, Serializable>(resultBoUserBean.getClass().getName(), resultBoUserBean));
		}
	    }
	} catch (Exception e) {
	    ApplicationLogBean applicationLogBean = new ApplicationLogBean();
	    applicationLogBean.setType(ApplicationLogBean.TYPE_ERROR);
	    applicationLogBean.setClazz(clazz);
	    applicationLogBean.setMethod(method);
	    applicationLogBean.setMessage(e.getMessage());
	    applicationLogService.createApplicationLog(applicationLogBean);
	}
	return entryBeans;
    }

    private Boolean isDataChange(MerchantUser merchantUser, MerchantUserBean merchantUserBean) {
	Boolean isChange = false;
	if (merchantUser != null && merchantUserBean != null) {
	    if (!merchantUser.getEmail().equals(merchantUserBean.getEmail()) || !merchantUser.getName().equals(merchantUserBean.getName())
		    || !merchantUser.getRole().equals(merchantUserBean.getRole())
		    || !merchantUser.getStatus().equals(merchantUserBean.getStatus())) {
		isChange = true;
	    }
	}
	return isChange;
    }

    private void createMerchantUserPasswordHistory(Long userId, String lastPasswordHash, String currentDateStr) {
	// todo
    }
}
